package App.Public.Lib;

import com.csvreader.CsvWriter;
import jxl.Workbook;
import jxl.WorkbookSettings;
import jxl.write.Label;
import jxl.write.WritableSheet;
import jxl.write.WritableWorkbook;

import java.io.File;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.nio.charset.Charset;
import java.util.ArrayList;

public class DataExport
{
    /**
     * 将一个对象的数据导出到excel里
     * @param o 目标对象
     * @param path 导出路径，导出文件格式为.xls
     * @throws Exception 如果路径不合法会抛出异常
     */
    public static void objectToXls(Object o,String path) throws Exception {
        WorkbookSettings settings=new WorkbookSettings();
        settings.setEncoding("UTF-8");
        path=pathCheck(path,".xls");
        WritableWorkbook workbook=Workbook.createWorkbook(new File(path),settings);
        WritableSheet sheet = workbook.createSheet("FIrst sheet",0);
        ArrayList<String> paraList =objectNameList(o);
        ArrayList<String> dataList=getObjectData(o);
        for(int i=0;i<paraList.size();i++)
        {
            sheet.addCell(new Label(i,0,paraList.get(i)));
        }
        for(int i=0;i<dataList.size();i++)
        {
            sheet.addCell(new Label(i,1,dataList.get(i)));
        }
        workbook.write();
        workbook.close();
    }

    /**
     * 将对象数组导出到Excel中
     * @param list  目标对象数组，注意数组里面的对象类型应该相同
     * @param path  导出的路径，导出文件格式为.xls
     * @throws Exception 如果路径不合法会抛出异常
     */
    public static<E> void objectListToXls(ArrayList<E> list,String path) throws Exception {
        WorkbookSettings settings=new WorkbookSettings();
        settings.setEncoding("UTF-8");
        path=pathCheck(path,".xls");
        WritableWorkbook workbook=Workbook.createWorkbook(new File(path),settings);
        WritableSheet sheet = workbook.createSheet("FIrst sheet",0);
        Object stdObj=list.get(0);
        ArrayList<String> paraList =objectNameList(stdObj);
        for(int i=0;i<paraList.size();i++)
        {
            sheet.addCell(new Label(i,0,paraList.get(i)));
        }
        for(int r=1;r<=list.size();r++)
        {
            Object targetObj=list.get(r-1);
            ArrayList<String> dataList=getObjectData(targetObj);
            for(int i=0;i<dataList.size();i++)
            {
                sheet.addCell(new Label(i,r,dataList.get(i)));
            }
        }
        workbook.write();
        workbook.close();
    }

    /**
     * 判断路径是否合法，并对路径进行处理
     * @param path 路径
     * @return 合法路径
     * @throws Exception 如果路径不合法会抛出异常
     */
    public static String pathCheck(String path,String type) throws Exception {
        int lastIndex=path.lastIndexOf('/');
        if(lastIndex==-1)
        {
            //如果不存在'/',则认为在根目录下
            if(!path.contains(type))
            {
                path+=type;
            }
            return path;
        }
        //首先判断路径是否合法
        String basePath=path.substring(0,lastIndex);
        if(!new File(basePath).isDirectory())
        {
            throw new Exception("路径不合法");
        }
        //判断路径是目录还是具体的文件名
        if(new File(path).isDirectory())
        {   //如果是目录
            if(!(path.lastIndexOf('/')==path.length()))
            {
                path+='/';
            }
            return path+="exportData.xls";
        }
        else
        {   //如果是文件名
            if(!path.contains(type))
            {
                path+=type;
            }
            return path;
        }
    }

    /**
     * 将对象数组的数据导出到CSV
     * @param list 对象数组
     * @param path 路径
     * @throws Exception 路径不合法或者list为null时候会丢异常
     */
    public static<E> void objectListToCsv(ArrayList<E> list,String path) throws Exception
    {
        //检查路径是否合法
        path=pathCheck(path,".csv");
        //检查list是否为null
        if(list==null)
        {
            throw new Exception("数据异常");
        }
        //初始化
        CsvWriter wr=new CsvWriter(path,',',Charset.forName("UTF-8"));
        //获取表头
        String[] nameList=ToStringArray(objectNameList(list.get(0)));
        wr.writeRecord(nameList);
        for(Object o:list)
        {
            wr.writeRecord(ToStringArray(getObjectData(o)));
        }
        wr.close();
    }


    private static String[] ToStringArray(ArrayList<String> list)
    {
        return list.toArray(new String[list.size()]);
    }

    private static ArrayList<String> objectNameList(Object o)
    {
        ArrayList<String> paraList=new ArrayList<>();
        Class cls = o.getClass();
        Field[] fields = cls.getDeclaredFields();
        AccessibleObject.setAccessible(fields, true);
        for(Field field:fields)
        {
            paraList.add(field.getName());
        }
        return paraList;
    }

    private static ArrayList<String> getObjectData(Object o) throws IllegalAccessException
    {
        ArrayList<String> dataList=new ArrayList<>();
        Class cls = o.getClass();
        Field[] fields = cls.getDeclaredFields();
        AccessibleObject.setAccessible(fields, true);
        for(Field field:fields)
        {
            if(field.get(o)==null)
            {
                dataList.add("");
            }
            else dataList.add(field.get(o).toString());
        }
        return dataList;
    }
}
